#ifndef UL_TIMER_H_ 
#define UL_TIMER_H_
#include <stdint.h>
#include <pthread.h>
#include <sys/time.h>
namespace LinuxNetworkUtility
{
  typedef void (*ul_timer_routine_t)(void *arg);
  class UlTimer
  {
  public:
    UlTimer();
    virtual ~UlTimer();

    /// initialize
    /// @param accuracy_ms time accuray in us, current the minimum is 10ms
    virtual int init(const int64_t accuracy_us);

    /// stop worker thread
    virtual void stop();

    /// get time elapsed since the process started, 1 ul minute = 2^26 us
    virtual int64_t get_cur_time_us() const
    {
      return cur_time_us_;
    } 
    virtual int64_t get_cur_time_ul_minute() const
    {
      return(cur_time_us_>>26);
    }

    virtual int64_t get_process_epoch_us() const
    {
      return(cur_time_us_ - process_epoch_begin_us_);
    }

    virtual int64_t get_process_epoch_ul_minute() const
    {
      return(cur_time_us_ - process_epoch_begin_us_)>>26;
    }

    virtual void set_cur_time_us(int64_t cur_time)
    {
      cur_time_us_ = cur_time;
    }


    virtual bool is_running() const
    {
      return worker_thread_is_running_;
    }

    virtual void get_accuracy(struct timeval &accuracy) const
    {
      accuracy = time_accuracy_;
    }

    virtual int register_timer_routine(ul_timer_routine_t routine, ul_timer_routine_t destroy_routine,
                                       void *arg, int64_t frenquency_us);

    virtual void unregister_timer_routine(ul_timer_routine_t routine);

    virtual void run_routines();

    static int64_t us_to_ul_minute(int64_t us)
    {
      return(us>>26);
    }

  private:
    static const int32_t UL_MAX_TIMER_ROUTINE_NUM = 2048;
    struct TimerRoutine
    {
      ul_timer_routine_t  routine_;
      ul_timer_routine_t  destroy_routine_;
      int64_t             frenquency_us_;
      int64_t             last_exec_time_us_;
      void *              arg_;
    };

    pthread_t worker_thread_;
    int64_t  process_epoch_begin_us_;
    volatile int64_t cur_time_us_;
    volatile bool      worker_thread_is_running_;
    struct    timeval   time_accuracy_;
    int32_t             registered_timer_routine_num_;
    TimerRoutine        routines_[UL_MAX_TIMER_ROUTINE_NUM];
    pthread_spinlock_t  spin_lock_;
  };
}  
#endif /* UL_TIMER_H_ */
